using System.Collections.Immutable;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;

namespace UnmanagedClass.Generator
{
    [Generator(LanguageNames.CSharp)]
    public class ParentClassGenerator : IIncrementalGenerator
    {
        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            // 筛选带有 UCBaseStruct 特性的结构体
            var candidates = context.SyntaxProvider.CreateSyntaxProvider(
                    predicate: IsCandidate,
                    transform: TransformToSymbol)
                .Where(s => s != null);

            var combo = context.CompilationProvider.Combine(candidates.Collect());
            context.RegisterSourceOutput(combo, Execute);
        }

        private static bool IsCandidate(SyntaxNode node, CancellationToken ct)
        {
            return node is StructDeclarationSyntax { AttributeLists.Count: > 0 };
        }

        private static ISymbol TransformToSymbol(GeneratorSyntaxContext ctx, CancellationToken ct)
        {
            var structDecl = (StructDeclarationSyntax)ctx.Node;
            foreach (var al in structDecl.AttributeLists)
            {
                foreach (var attr in al.Attributes)
                {
                    var ctor = ctx.SemanticModel.GetSymbolInfo(attr).Symbol as IMethodSymbol;
                    if (ctor == null) continue;
                    var at = ctor.ContainingType;
                    if (at != null && (at.Name == "UCBaseStruct" || at.Name == "UCBaseStructAttribute"))
                    {
                        return ctx.SemanticModel.GetDeclaredSymbol(structDecl);
                    }
                }
            }

            return null;
        }

        private void Execute(SourceProductionContext spc, (Compilation Left, ImmutableArray<ISymbol> Right) pair)
        {
            var compilation = pair.Left;
            var symbols = pair.Right;
            if (symbols == null) return;

            foreach (var sym in symbols)
            {
                if (sym is not INamedTypeSymbol template) continue;

                // 检查是否实现了 IDisposable
                bool implementsIDisposable = false;
                foreach (var interfaceSymbol in template.AllInterfaces)
                {
                    if (interfaceSymbol.ToDisplayString() == "System.IDisposable")
                    {
                        implementsIDisposable = true;
                        break;
                    }
                }

                if (!implementsIDisposable)
                {
                    // 报告错误 UC0008
                    var loc = template.Locations.Length > 0 ? template.Locations[0] : Location.None;
                    spc.ReportDiagnostic(Diagnostic.Create(Diag.UCBaseStructMustImplementIDisposable, loc, template.Name));
                    continue;
                }

                // 生成代码
                var source = GenerateParentSource(template);
                var fileName = $"{template.ContainingNamespace.Name}_{template.Name}.gen.cs";
                spc.AddSource(fileName, SourceText.From(source, Encoding.UTF8));
            }
        }

        private string GenerateParentSource(INamedTypeSymbol structSymbol)
        {
            var sb = new StringBuilder();
            sb.AppendLine("// <auto-generated/>");
            sb.AppendLine("#pragma warning disable 1591");
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Runtime.InteropServices;");
            sb.AppendLine("using DA.AnimGraph.Share;");
            sb.AppendLine("using Battle.Math;");
            sb.AppendLine();

            var namespaceName = structSymbol.ContainingNamespace.ToDisplayString();
            if (!structSymbol.ContainingNamespace.IsGlobalNamespace)
            {
                sb.AppendLine($"namespace {namespaceName}");
                sb.AppendLine("{");
            }

            // 生成 Obsolete 结构体
            sb.AppendLine($"    [Obsolete(\"请使用 {structSymbol.Name}UC 替代\", error: true)]");
            sb.AppendLine($"    public unsafe partial struct {structSymbol.Name}");
            sb.AppendLine("    {");
            // 为每个UCInterface方法生成非静态的空实现（去掉第一个void* self参数）
            foreach (var member in structSymbol.GetMembers())
            {
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCInterfaceAttribute"))
                {
                    // 跳过第一个void* self参数
                    var parameters = method.Parameters.Skip(1);
                    var parameterList = string.Join(", ", parameters.Select(p => $"{p.Type.ToDisplayString()} {p.Name}"));
                    // 生成非静态方法（去掉static关键字）
                    sb.AppendLine($"        public {method.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} {method.Name}({parameterList}) => throw new Exception();");
                }
            }
            sb.AppendLine("    }");
            sb.AppendLine();

            // 生成 UC 结构体
            sb.AppendLine("    [StructLayout(LayoutKind.Sequential)]");
            sb.AppendLine($"    public unsafe struct {structSymbol.Name}UC");
            sb.AppendLine("    {");
            // 修正：虚函数表类型名称应该是基类型名称 + "UCVT"
            sb.AppendLine($"        public {structSymbol.Name}UCVT* __vt__;");

            // 添加字段 - 复制所有非静态字段
            foreach (var member in structSymbol.GetMembers())
            {
                if (member is IFieldSymbol field && !field.IsStatic)
                {
                    sb.AppendLine($"        public {field.Type.ToDisplayString()} {field.Name};");
                }
            }

            sb.AppendLine();

            // 添加 UCInterface 方法
            foreach (var member in structSymbol.GetMembers())
            {
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCInterfaceAttribute"))
                {
                    // 生成实例方法
                    var parameters = method.Parameters.Skip(1); // 跳过第一个 void* self 参数
                    var parameterList = parameters.Any() ? string.Join(", ", parameters.Select(p => $"{p.Type.ToDisplayString()} {p.Name}")) : "";
                    var argumentList = parameters.Any() ? string.Join(", ", parameters.Select(p => p.Name)) : "";

                    // 确定是否需要 return 语句
                    bool hasReturnValue = method.ReturnType.SpecialType != SpecialType.System_Void;
                    string returnKeyword = hasReturnValue ? "return " : "";

                    sb.AppendLine($"        public {method.ReturnType.ToDisplayString()} {method.Name}({parameterList})");
                    sb.AppendLine("        {");
                    sb.AppendLine($"            fixed ({structSymbol.Name}UC* selfPtr = &this)");
                    sb.AppendLine("            {");

                    if (parameters.Any())
                    {
                        sb.AppendLine($"                {returnKeyword}selfPtr->__vt__->{method.Name}(selfPtr, {argumentList});");
                    }
                    else
                    {
                        sb.AppendLine($"                {returnKeyword}selfPtr->__vt__->{method.Name}(selfPtr);");
                    }

                    sb.AppendLine("            }");
                    sb.AppendLine("        }");
                    sb.AppendLine();
                }
            }

            // 复制所有非UCInterface的成员（包括静态方法、静态字段等）
            foreach (var member in structSymbol.GetMembers())
            {
                // 跳过特殊处理的成员
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCInterfaceAttribute"))
                {
                    continue;
                }

                // 跳过已经处理的字段
                if (member is IFieldSymbol field && !field.IsStatic)
                {
                    continue;
                }

                // 复制其他所有成员
                var syntaxRef = member.DeclaringSyntaxReferences.FirstOrDefault();
                if (syntaxRef != null)
                {
                    var syntax = syntaxRef.GetSyntax();
                    if (syntax != null)
                    {
                        // 跳过属性的下层节点
                        if (syntax is AccessorDeclarationSyntax || syntax is ArrowExpressionClauseSyntax) continue;
                        // 复制成员
                        var memberText = syntax.ToFullString();
                        sb.AppendLine(memberText);
                    }
                }
            }

            sb.AppendLine("    }");
            sb.AppendLine();

            // 生成 VT 结构体 - 修正：类型名应该是基类型名称 + "UCVT"
            sb.AppendLine($"    public unsafe struct {structSymbol.Name}UCVT");
            sb.AppendLine("    {");

            // 添加函数指针字段和属性
            foreach (var member in structSymbol.GetMembers())
            {
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCInterfaceAttribute"))
                {
                    var parameters = method.Parameters.Skip(1); // 跳过第一个 void* self 参数
                    var parameterTypes = parameters.Any() ? string.Join(", ", parameters.Select(p => p.Type.ToDisplayString())) : "";
                    var returnType = method.ReturnType.ToDisplayString();

                    sb.AppendLine($"        public void* {method.Name}Ptr;");

                    if (parameters.Any())
                    {
                        sb.AppendLine($"        public delegate* managed<void*, {parameterTypes}, {returnType}> {method.Name}");
                    }
                    else
                    {
                        sb.AppendLine($"        public delegate* managed<void*, {returnType}> {method.Name}");
                    }

                    sb.AppendLine("        {");

                    if (parameters.Any())
                    {
                        sb.AppendLine($"            get => (delegate* managed<void*, {parameterTypes}, {returnType}>){method.Name}Ptr;");
                        sb.AppendLine($"            set {{ {method.Name}Ptr = value; }}");
                    }
                    else
                    {
                        sb.AppendLine($"            get => (delegate* managed<void*, {returnType}>){method.Name}Ptr;");
                        sb.AppendLine($"            set {{ {method.Name}Ptr = value; }}");
                    }

                    sb.AppendLine("        }");
                    sb.AppendLine();
                }
            }

            sb.AppendLine("    }");

            if (!structSymbol.ContainingNamespace.IsGlobalNamespace)
            {
                sb.AppendLine("}");
            }

            return sb.ToString();
        }
    }
}